import React, { useContext, useReducer } from 'react'
import { Button, Checkbox, Form, Icon, Input, Radio, Tooltip, message } from 'antd'
import get from 'lodash/get'
import { useDeepCompareEffect } from 'ahooks'
import classNames from 'classnames'
import { isEqual } from 'lodash'
import ForMultipleValue from '../ForMultipleValue'
import {
  ARRAY_MAPPING,
  ARRAY_PASS_THROUGH,
  ARRAY_REPLACEMENT,
  CONDITION_TRUE,
  CONST_RULE,
  LEAF_MAPPING,
  MULTIPLE_VALUE_RULE,
  OBJECT_MAPPING,
  OBJECT_PASS_THROUGH,
  OBJECT_REPLACEMENT,
  RULES,
} from '../../settings'
import PreProcess from '../PreProcess'
import Mapper from '../Mapper'
import { getCurrentGroup, hasGroups } from './utils'
import { ARRAY_TYPE, OBJECT_TYPE } from './settings'
import styles from './styles.less'
import { getUniqueID } from '@/utils/utils'
import Context from '@/pages/Transformer/components/TargetPanel/targetContext'
import ConditionGroup from '@/components/ConditionGroup'
import SourceContext from '@/pages/Transformer/components/SourcePanel/context'
import CustomHandlerSelector from '@/components/CustomHandlerSelector'

export const MODES = [
  { title: '简洁模式', value: 'basic' },
  { title: '高级模式', value: 'advanced' },
]

function getDefautConfigType(nodeType) {
  let t = LEAF_MAPPING
  if (nodeType === ARRAY_TYPE)
    t = ARRAY_MAPPING

  if (nodeType === OBJECT_TYPE)
    t = OBJECT_MAPPING

  return t
}

function getDefautRule(nodeType) {
  const t = getDefautConfigType(nodeType)

  return {
    __id: getUniqueID('RULE'),
    condition: {
      type: 'AlwaysTrue',
    },
    config: {
      type: t,
      mapping: [],
    },
  }
}

const initialState = {
  current: {},
  rules: [],
  mode: 'basic',
}

function reducer(state, action) {
  const { type, payload } = action

  if (type === 'sync_props') {
    return {
      ...state,
      ...payload,
    }
  }

  if (type === 'change_group_name') {
    return {
      ...state,
      groupName: payload,
    }
  }

  if (type === 'change_rules') {
    const { index, newRule } = payload

    const r = [...state.rules]
    r[index] = newRule.__id
      ? newRule
      : {
          ...newRule,
          __id: getUniqueID('RULE'),
        }
    // console.log(r);
    return {
      ...state,
      rules: r,
    }
  }

  if (type === 'change_post_operations') {
    const { index, postOperations } = payload

    const r = [...state.rules]
    r[index].config.postOperations = postOperations
    return {
      ...state,
      rules: r,
    }
  }

  if (type === 'change_mode') {
    const { mode } = payload

    if (mode === 'basic') {
      return {
        ...state,
        mode,
        rules: [state.rules[0]],
      }
    }

    return {
      ...state,
      mode,
    }
  }

  if (type === 'add_rule') {
    const { nodeType } = payload
    const r = [...state.rules]
    r.push(getDefautRule(nodeType))
    return {
      ...state,
      rules: r,
    }
  }

  if (type === 'delete_rule') {
    const { index } = payload
    const r = [...state.rules]
    r.splice(index, 1)

    return {
      ...state,
      rules: r,
    }
  }

  throw new Error()
}

function ConfigPanel({ onClose, current, nodePath, parent }) {
  const [state, dispatch] = useReducer(reducer, initialState)

  const { dispatch: D } = useContext(Context)

  const nodeType = get(current, 'nodeType')

  const isContainerNode = nodeType === OBJECT_TYPE || nodeType === ARRAY_TYPE

  useDeepCompareEffect(() => {
    let rules
    const node = { ...current }
    if (hasGroups(node)) {
      const group = getCurrentGroup(node)
      rules = get(group, 'rules') || []

      if (Array.isArray(rules) && rules.length > 0) {
        rules = rules.map((k) => {
          if (!k.__id)
            return { ...k, __id: getUniqueID('RULE') }

          return k
        })
      }
      else {
        rules = [getDefautRule(nodeType)]
      }

      // 当前副本下的所有rules

      const isBasic
        = rules.length === 0
        || (rules.length === 1 && get(rules, '[0].condition.type') === CONDITION_TRUE)

      // 默认值为`简洁`模式
      const mode = isBasic ? 'basic' : 'advanced'

      dispatch({
        type: 'sync_props',
        payload: { current: node, groupName: get(group, 'groupName') || `副本${1}`, rules, mode },
      })
    }
    else {
      rules = [getDefautRule(nodeType)]

      node.groups = [
        {
          indexes: [...node.prefix, 0],
          groupName: `副本${1}`,
          rules,
        },
      ]

      dispatch({
        type: 'sync_props',
        payload: { current: node, rules, groupName: `副本${1}`, mode: 'basic' },
      })
    }
  }, [current, nodeType])

  const handleSave = () => {
    const ins = getCurrentGroup(current)
    const groups = get(current, 'groups')
    const indexes = get(ins, 'indexes')

    const index = groups.findIndex(g => isEqual(g.indexes, indexes))

    if (nodePath !== '')
      nodePath += '.'

    if (index !== -1) {
      groups.splice(index, 1, { ...ins, groupName: state.groupName, rules: state.rules })

      D({
        type: 'update_node_group_attr',
        payload: {
          value: groups,
          path: `${nodePath}groups`,
          groups,
          parent,
          current,
        },
      })
    }
    else {
      const p = get(current, 'prefix') || []
      const g = get(current, 'groupIndex') || 0

      D({
        type: 'update_node_group_attr',
        payload: {
          value: [
            ...groups,
            { ...ins, indexes: [...p, g], groupName: state.groupName, rules: state.rules },
          ],
          path: `${nodePath}groups`,
          groups,
          parent,
          current,
        },
      })
    }
  }

  // 当前副本下的所有rules
  const r = get(state, 'rules')
  const rules = r === undefined || r.length === 0 ? [getDefautRule(nodeType)] : r

  const { state: TContext = {} } = useContext(SourceContext)

  const treeData = [get(TContext, 'data')]

  const handleReset = () => {
    const currentGroup = getCurrentGroup(current)
    if (currentGroup) {
      D({
        type: 'reset_current_instance',
        payload: {
          current,
          nodePath,
          currentGroup,
        },
      })
    }
  }

  return (
    <>
      <Form>
        <Radio.Group
          value={state.mode}
          buttonStyle="solid"
          className="margin-z"
          style={{ display: 'block' }}
          onChange={(e) => {
            const mode = e.target.value
            dispatch({ type: 'change_mode', payload: { mode, nodeType } })
          }}
        >
          {MODES.map(k => (
            <Radio.Button key={k.value} value={k.value}>
              {k.title}
            </Radio.Button>
          ))}
        </Radio.Group>
        {current.nodeType === ARRAY_TYPE && (
          <Form.Item label="副本名称" required>
            <Input
              placeholder=""
              value={state.groupName}
              onChange={(e) => {
                dispatch({ type: 'change_group_name', payload: e.target.value })
              }}
              onPressEnter={handleSave}
            />
          </Form.Item>
        )}

        {rules.map((k, i) => (
          <div key={k.__id} className={classNames({ [styles.rule]: state.mode === 'advanced' })}>
            {state.mode === 'advanced' && (
              <>
                <div className={styles.counter}>
                  <span className={styles.num}>{i + 1}</span>

                  <span
                    className={classNames(styles.delete, 'text-danger')}
                    onClick={() => {
                      if (rules.length === 1) {
                        message.warning('只剩一条了')
                        return
                      }
                      dispatch({ type: 'delete_rule', payload: { index: i } })
                    }}
                  >
                    <Tooltip title="删除">
                      <Icon type="close" />
                    </Tooltip>
                  </span>
                </div>
                <Form.Item label="条件类型" required>
                  <ConditionGroup
                    treeData={treeData}
                    value={get(k, 'condition')}
                    onChange={(value) => {
                      dispatch({
                        type: 'change_rules',
                        payload: {
                          index: i,
                          newRule: {
                            ...k,
                            condition: value,
                          },
                        },
                      })
                    }}
                  />
                </Form.Item>
              </>
            )}
            <Form.Item label="规则类型" required>
              <Radio.Group
                value={get(k, 'config.type')}
                className="margin-z"
                style={{ display: 'block' }}
                onChange={(e) => {
                  dispatch({
                    type: 'change_rules',
                    payload: {
                      index: i,
                      newRule: {
                        condition: k.condition,
                        config: {
                          type: e.target.value,
                        },
                        // __id: getUniqueID('RULE'),
                        // ...getDefautRule(nodeType),
                      },
                    },
                  })
                }}
              >
                {RULES.filter((k) => {
                  // 对于Object和Array节点只有 “映射”

                  if (nodeType === OBJECT_TYPE) {
                    return (
                      k.value === OBJECT_MAPPING
                      || k.value === OBJECT_PASS_THROUGH
                      || k.value === OBJECT_REPLACEMENT
                      || k.value === CONST_RULE
                    )
                  }

                  if (nodeType === ARRAY_TYPE) {
                    return (
                      k.value === ARRAY_MAPPING
                      || k.value === ARRAY_PASS_THROUGH
                      || k.value === ARRAY_REPLACEMENT
                      || k.value === CONST_RULE
                    )
                  }

                  // 叶子节点（String、Integer、Double、Boolean）有3种
                  return ![
                    OBJECT_MAPPING,
                    ARRAY_MAPPING,
                    OBJECT_PASS_THROUGH,
                    ARRAY_PASS_THROUGH,
                    OBJECT_REPLACEMENT,
                    ARRAY_REPLACEMENT,
                  ].includes(k.value)
                }).map(k => (
                  <Radio key={k.value} value={k.value}>
                    {k.title}
                  </Radio>
                ))}
              </Radio.Group>
            </Form.Item>

            {/* 常量 */}
            {get(k, 'config.type') === CONST_RULE && (
              <Input
                placeholder="输入常量"
                value={get(k, 'config.value.stringValue')}
                onChange={(e) => {
                  dispatch({
                    type: 'change_rules',
                    payload: {
                      index: i,
                      newRule: {
                        ...k,
                        condition: k.condition,
                        config: {
                          type: k.config.type,
                          value: {
                            stringValue: e.target.value,
                            isString: isContainerNode
                              ? false
                              : typeof get(k, 'config.value.isString') === 'boolean'
                                ? get(k, 'config.value.isString')
                                : true,
                          },
                        },
                      },
                    },
                  })
                }}
                onPressEnter={handleSave}
                allowClear
                addonAfter={
                  <Tooltip title="是否当成字符串处理">
                    <Checkbox
                      checked={
                        isContainerNode
                          ? false
                          : typeof get(k, 'config.value.isString') === 'boolean'
                            ? get(k, 'config.value.isString')
                            : true
                      }
                      onChange={(e) => {
                        dispatch({
                          type: 'change_rules',
                          payload: {
                            index: i,
                            newRule: {
                              ...k,
                              condition: k.condition,
                              config: {
                                type: k.config.type,
                                value: {
                                  stringValue: get(k, 'config.value.stringValue'),
                                  isString: isContainerNode ? false : e.target.checked,
                                },
                              },
                            },
                          },
                        })
                      }}
                      disabled={isContainerNode}
                    />
                  </Tooltip>
                }
              />
            )}

            {/* 映射 */}
            {[OBJECT_MAPPING, ARRAY_MAPPING, LEAF_MAPPING].includes(get(k, 'config.type')) && (
              <Mapper
                treeData={treeData}
                value={get(k, 'config.mapping')}
                onChange={(data) => {
                  dispatch({
                    type: 'change_rules',
                    payload: {
                      index: i,
                      newRule: {
                        ...k,
                        condition: k.condition,
                        config: { ...k.config, type: k.config.type, mapping: data },
                      },
                    },
                  })
                }}
              />
            )}

            {/* 多值运算 */}
            {get(k, 'config.type') === MULTIPLE_VALUE_RULE && (
              <ForMultipleValue
                treeData={treeData}
                value={get(k, 'config')}
                onChange={(data) => {
                  dispatch({
                    type: 'change_rules',
                    payload: {
                      index: i,
                      newRule: {
                        ...k,
                        condition: k.condition,
                        config: { type: k.config.type, ...data },
                      },
                    },
                  })
                }}
              />
            )}

            {/* 数组替换 */}
            {get(k, 'config.type') === ARRAY_REPLACEMENT && (
              <CustomHandlerSelector
                url="/transform/listCustomArrayNodeTransformers"
                value={get(k, 'config')}
                onChange={(data) => {
                  dispatch({
                    type: 'change_rules',
                    payload: {
                      index: i,
                      newRule: {
                        ...k,
                        condition: k.condition,
                        config: { type: k.config.type, ...data },
                      },
                    },
                  })
                }}
              />
            )}

            {/* 对象替换 */}
            {get(k, 'config.type') === OBJECT_REPLACEMENT && (
              <CustomHandlerSelector
                url="/transform/listCustomObjectNodeTransformers"
                value={get(k, 'config')}
                onChange={(data) => {
                  dispatch({
                    type: 'change_rules',
                    payload: {
                      index: i,
                      newRule: {
                        ...k,
                        condition: k.condition,
                        config: { type: k.config.type, ...data },
                      },
                    },
                  })
                }}
              />
            )}

            {/* 数组透传 */}
            {(get(k, 'config.type') === ARRAY_PASS_THROUGH
              || get(k, 'config.type') === OBJECT_PASS_THROUGH) && (
              <Mapper
                treeData={treeData}
                value={get(k, 'config.mapping')}
                onChange={(data) => {
                  dispatch({
                    type: 'change_rules',
                    payload: {
                      index: i,
                      newRule: {
                        ...k,
                        condition: k.condition,
                        config: { ...k.config, type: k.config.type, mapping: data },
                      },
                    },
                  })
                }}
              />
            )}

            {/* 后置操作 */}
            {[
              OBJECT_PASS_THROUGH,
              ARRAY_PASS_THROUGH,
              LEAF_MAPPING,
              OBJECT_REPLACEMENT,
              ARRAY_REPLACEMENT,
              MULTIPLE_VALUE_RULE,
              CONST_RULE,
              OBJECT_MAPPING,
            ].includes(get(k, 'config.type')) && (
              <PreProcess
                // filter={
                //   [LEAF_MAPPING].includes(get(k, 'config.type'))
                //     ? undefined
                //     : ({ value }) => [PRE_PROCESS_CUSTOM_TRANSFORMER].includes(value)
                // }
                onChange={(value) => {
                  dispatch({
                    type: 'change_post_operations',
                    payload: {
                      index: i,
                      postOperations: value,
                    },
                  })
                }}
                value={get(k, 'config.postOperations') || []}
              />
            )}
          </div>
        ))}
      </Form>
      <div className={styles.advFooter}>
        <div className="pull-left">
          {/* <Button
            type="link"
            className="text-danger"
            onClick={() => {
              dispatch({
                type: 'add_rule',
                payload: {
                  nodeType,
                },
              });
            }}
          >
            清空配置
          </Button> */}
          {state.mode === 'advanced' && (
            <Button
              icon="plus"
              type="link"
              style={{ padding: 0 }}
              onClick={() => {
                dispatch({
                  type: 'add_rule',
                  payload: {
                    nodeType,
                  },
                })
              }}
            >
              添加一组规则
            </Button>
          )}
        </div>
        <div className="pull-right">
          <Button style={{ marginRight: 8 }} onClick={() => onClose(false)}>
            取消
          </Button>
          <Button style={{ marginRight: 8 }} onClick={handleReset}>
            重置
          </Button>
          <Button type="primary" onClick={() => handleSave()}>
            保存
          </Button>
        </div>
      </div>
    </>
  )
}

export default Form.create()(ConfigPanel)
